package com.yuantong.xyerp.rest.config.shiro.jwt;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yuantong.xyerp.core.api.enums.EnumMsgCode;
import com.yuantong.xyerp.core.api.exception.YuantongException;
import com.yuantong.xyerp.core.api.model.base.RestResponseModel;
import com.yuantong.xyerp.core.api.common.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Date;


@Slf4j
public class JwtUtil {
    public static final String AUTH_HEADER_KEY = "Authorization";

    public static final String TOKEN_PREFIX = "Bearer ";

    private static final String SECRET = "6f99171ee48e4c5f9ed52f42f2eded16";

    private static final long TOKE_EXPIRE_TIME = Constant.TOKE_EXPIRE_TIME;
    // private static final long TOKE_EXPIRE_TIME = 45;


    public static String createToken(String loginName, int passwordHashCode) {
        try {
            // 此处过期时间是以毫秒为单位，所以乘以1000
            Date date = new Date(System.currentTimeMillis() + TOKE_EXPIRE_TIME * 1000);
            Algorithm algorithm = Algorithm.HMAC256(SECRET + passwordHashCode);
            // 附带account帐号信息
            return JWT.create()
                    .withClaim(Constant.LOGIN_NAME, loginName)
                    .withIssuedAt(new Date())
                    .withExpiresAt(date) // 定义好的过期时间
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            log.error("JWTToken加密出现UnsupportedEncodingException异常:{}", e.getMessage());
            throw new YuantongException("500","JWTToken加密出现UnsupportedEncodingException异常:" + e.getMessage());
        }
    }



    public static String getClaim(String token, String claim) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            // 只能输出String类型，如果是其他类型返回null
            return jwt.getClaim(claim).asString();
        } catch (JWTDecodeException e) {
            log.error("解密Token中的公共信息出现JWTDecodeException异常:{}", e.getMessage());
            throw new YuantongException("500", "解密Token中的公共信息出现JWTDecodeException异常:" + e.getMessage());
        }
    }


    public static boolean verify(String token, int passwordHashCode) throws UnsupportedEncodingException {
            Algorithm algorithm = Algorithm.HMAC256(SECRET + passwordHashCode);
            JWTVerifier verifier = JWT.require(algorithm)
                    .acceptExpiresAt(15)
                    .build();
            verifier.verify(token);
            return true;
    }

    /**
     * 判断过期
     * @param token
     * @return
     */
    public static boolean isExpire(String token){
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getExpiresAt().getTime() - System.currentTimeMillis() < 0;
    }

    /**
     * 判断是否接近过期过期
     * @param token
     * @return
     */
    public static boolean isAlmostExpire(String token){
        DecodedJWT jwt = JWT.decode(token);
        long result =  jwt.getExpiresAt().getTime() - System.currentTimeMillis();
        // 还有 两天 过期
        return result < 60 * 60 * 24 * 2 * 1000 && result > 0;
    }


    /**
     * 无需转发，直接返回Response信息
     */
    private static void response401(HttpServletResponse response) {

        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try (PrintWriter out = response.getWriter()) {
            String data = JSON.toJSONString(RestResponseModel.FAIL(EnumMsgCode.USER_NOT_LOGGED_IN));
            out.append(data);
        } catch (IOException e) {
            log.error("直接返回Response信息出现IOException异常:{}", e.getMessage());
            throw new YuantongException("9999","直接返回Response信息出现IOException异常:" + e.getMessage());
        }
    }

}
